#include "io.h"

/* 所有的IO端口的计算都是相对于数据端口, 因为所有的串行端口 (COM1, COM2, COM3, COM4)
 * 都有它们自己对应的端口, 但是Base addr是不同的
 */

#define SERIAL_COM1_BASE                0x3F8

#define SERIAL_DATA_PORT(base)          (base)
#define SERIAL_FIFO_COMMAND_PORT(base)  ((base) + 2)
#define SERIAL_LINE_COMMAND_PORT(base)  ((base) + 3)
#define SERIAL_MODEM_COMMAND_PORT(base) ((base) + 4)
#define SERIAL_LINE_STATUS_PORT(base)   ((base) + 5)

// 告诉串行端口首先传输数据高8bit, 接着是低8位
#define SERIAL_LINE_ENABLE_DLAB         0x80

// 这里告诉串行端口的传输速率
void serial_configure_baud_rate(unsigned short com, unsigned short divisor) {
    // 首先告诉串行端口进行速率设置
    outb(SERIAL_LINE_COMMAND_PORT(com), 
        SERIAL_LINE_ENABLE_DLAB);
    // 接着设置高8位
    outb(SERIAL_DATA_PORT(com),
        (divisor >> 8) & 0x00FF);
    // 接着设置低8位
    outb(SERIAL_DATA_PORT(com),
        divisor & 0x00FF);
}

// 配置串行端口数据发送的方式:
// 这里的0x3表示8位数据, 其余都设置位disable
void serial_configure_line(unsigned short com) {
    outb(SERIAL_LINE_COMMAND_PORT(com), 0x03);
}

// 配置串行端口的FIFO队列
void serial_configure_fifo(unsigned short com) {
    outb(SERIAL_FIFO_COMMAND_PORT(com), 0xC7);
}

// 配置Modem
void serial_configure_modem(unsigned short com) {
    outb(SERIAL_MODEM_COMMAND_PORT(com), 0x03);
}

// 检查FIFO队列是否为空
// 0表示FIFO为非空
// 1表示FIFO为空
int serial_is_transmit_fifo_empty(unsigned int com) {
    return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20;
}